/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkPs/MkPsMuxer.h"
#include "MkPs/MkPsDemuxer.h"
#include "MkMedia/MkMediaUtil.h"
#include "MkPs/MkPsFileSource.h"
#include "MkEvent/MkTimer.h"

void ParseH265()
{
    //FILE *fp265 = fopen("C:/Workspace/media/ps265.dat", "rb");
    //FILE *fpVideo = fopen("C:/Workspace/media/ps.265", "wb");
    //FILE *fpAudio = fopen("C:/Workspace/media/ps.265.aac", "wb");
    //FILE *fpOutPs = fopen("C:/Workspace/media/ps265.out.dat", "wb");
    //FILE *fp265 = fopen("D:/mediaTest/ps265.dat", "rb");
    //FILE *fpVideo = fopen("D:/mediaTest/ps.265", "wb");
    //FILE *fpAudio = fopen("D:/mediaTest/ps.265.aac", "wb");
    //FILE *fpOutPs = fopen("D:/mediaTest/ps265.out.dat", "wb");
    //CMkTimer Timer;
    //CMkTimer* pTimer = &Timer;

    //CMkPsFileSource FileSource(fp265, &Timer, [fpVideo, fpAudio, fpOutPs, pTimer](const MkEsPacket& EsPacket, const CMkVideoParam& VideoParam, const CMkAudioParam& AudioParam) {
    //    CMkPsFileSource *psFileSource = dynamic_cast<CMkPsFileSource*>(pMediaSource);
    //    //audio
    //    if (EsPacket.BufferList.Empty()) {
    //        fclose(fpVideo);
    //        fclose(fpAudio);
    //        fclose(fpOutPs);
    //        pTimer->LoopBreak();
    //        return;
    //    }
    //    if (EsPacket.CodecType > MkCodecCavs) {
    //        MkListBuffer::const_iterator it = EsPacket.BufferList.GetBufferList().begin();
    //        for (; it != EsPacket.BufferList.GetBufferList().end(); it++) {
    //            fwrite(it->GetBuffer(), 1, it->GetLength(), fpAudio);
    //        }
    //    } else {
    //        MkListBuffer::const_iterator it = EsPacket.BufferList.GetBufferList().begin();
    //        for (; it != EsPacket.BufferList.GetBufferList().end(); it++) {
    //            fwrite(&NaluStartCode, 1, 4, fpVideo);
    //            fwrite(it->GetBuffer(), 1, it->GetLength(), fpVideo);
    //        }
    //    }
    //    CMkBufferList ReBufferList;
    //    Uint32 nUsed = 0;
    //    Uint8 pBuf[Len2K] = { 0 };
    //    CMkPsMuxer::PacketEsPacket(pMediaSource->GetVideoParam(), pMediaSource->GetAudioParam(), EsPacket, pBuf, Len2K, nUsed, ReBufferList);
    //    MkListBuffer::const_iterator it = ReBufferList.GetBufferList().begin();
    //    for (; it != ReBufferList.GetBufferList().end(); it++) {
    //        fwrite(it->GetBuffer(), 1, it->GetLength(), fpOutPs);
    //    }
    //}, [](CMkMediaSource* pMediaSource, Uint32 ErrorCode) {

    //});
    //FileSource.ScanFile();
    //FileSource.StartMediaSource();
    //Timer.Dispatch();
}

void ParseH264()
{
    //FILE *fp265 = fopen("D:/mediaTest/ps.dat", "rb");
    //FILE *fpVideo = fopen("D:/mediaTest/ps.264", "wb");
    //FILE *fpAudio = fopen("D:/mediaTest/ps.264.aac", "wb");
    //FILE *fpOutPs = fopen("D:/mediaTest/ps264.out.dat", "wb");
    //FILE *fp265 = fopen("C:/Workspace/media/ps.dat", "rb");
    //FILE *fp265 = fopen("C:/Workspace/media/ps.dat", "rb");
    //FILE *fpVideo = fopen("C:/Workspace/media/ps.264", "wb");
    //FILE *fpAudio = fopen("C:/Workspace/media/ps.264.aac", "wb");
    //FILE *fpOutPs = fopen("C:/Workspace/media/ps264.out.dat", "wb");
    //CMkTimer Timer;
    //CMkTimer* pTimer = &Timer;

    //CMkPsFileSource FileSource(fp265, &Timer, [](CMkMediaSource* pMediaSource, Uint32 ErrorCode) {
    //    return NoneError;
    //}, [fpVideo, fpAudio, fpOutPs, pTimer,FileSource](const MkEsPacket& EsPacket, const CMkVideoParam& VideoParam, const CMkAudioParam& AudioParam) {
    //    //audio
    //    if (EsPacket.BufferList.Empty()) {
    //        fclose(fpVideo);
    //        fclose(fpAudio);
    //        fclose(fpOutPs);
    //        pTimer->LoopBreak();
    //        return;
    //    }
    //    if (EsPacket.CodecType > MkCodecCavs) {
    //        MkListBuffer::const_iterator it = EsPacket.BufferList.GetBufferList().begin();
    //        for (; it != EsPacket.BufferList.GetBufferList().end(); it++) {
    //            //add adts header
    //            Uint8 pAdts[Len16] = { 0 };
    //            CMkMediaUtil::CreateAacAdts(pMediaSource->GetAudioParam().GetObjectType(), pMediaSource->GetAudioParam().GetSampleRate(), pMediaSource->GetAudioParam().GetChannel(), it->GetLength(), pAdts);
    //            fwrite(pAdts, 1, MkAacAdtsLen, fpAudio);
    //            fwrite(it->GetBuffer(), 1, it->GetLength(), fpAudio);
    //        }
    //    } else {
    //        MkListBuffer::const_iterator it = EsPacket.BufferList.GetBufferList().begin();
    //        for (; it != EsPacket.BufferList.GetBufferList().end(); it++) {
    //            fwrite(&NaluStartCode, 1, 4, fpVideo);
    //            fwrite(it->GetBuffer(), 1, it->GetLength(), fpVideo);
    //        }
    //    }
    //    //if (MkCodecAac == EsPacket.CodecType) {
    //    //    return;
    //    //}

    //    CMkBufferList ReBufferList;
    //    Uint32 nUsed = 0;
    //    Uint8 pBuf[Len2K] = { 0 };
    //    CMkPsMuxer::PacketEsPacket(pMediaSource->GetVideoParam(), pMediaSource->GetAudioParam(), EsPacket, pBuf, Len2K, nUsed, ReBufferList);
    //    MkListBuffer::const_iterator it = ReBufferList.GetBufferList().begin();
    //    for (; it != ReBufferList.GetBufferList().end(); it++) {
    //        fwrite(it->GetBuffer(), 1, it->GetLength(), fpOutPs);
    //    }
    //});
    //FileSource.ScanFile();
    //FileSource.StartMediaSource();
    //Timer.Dispatch();
}


CMkTimer* g_pTimer = nullptr;
void PsDemuxer(const MkString& PsFile, const MkString& AudioFile, const MkString& VideoFile)
{
    FILE *fpPs = fopen(PsFile.c_str(), "rb");
    FILE *fpVideo = fopen(VideoFile.c_str(), "wb");
    FILE *fpAudio = fopen(AudioFile.c_str(), "wb");
    CMkPsFileSource*  pFileSource = new CMkPsFileSource(fpPs, g_pTimer);
    pFileSource->StartMediaSource([](CMkMediaSource* pMediaSource, Uint32 ErrorCode) {
        return NoneError;
    }, [fpVideo, fpAudio, fpPs, pFileSource](const MkEsPacket& EsPacket, const CMkVideoParam& VideoParam, const CMkAudioParam& AudioParam) {
        //audio
        if (EsPacket.BufferList.Empty()) {
            g_pTimer->LoopBreak();
            fclose(fpVideo);
            fclose(fpAudio);
            fclose(fpPs);
            pFileSource->StopMediaSource();
            return NoneError;
        }
        if (EsPacket.CodecType > MkCodecCavs) {
            MkListBuffer::const_iterator it = EsPacket.BufferList.GetBufferList().begin();
            for (; it != EsPacket.BufferList.GetBufferList().end(); it++) {
                if (MkCodecAac == EsPacket.CodecType) {
                    Uint8 pAdts[MkAacAdtsLen] = { 0 };
                    CMkMediaUtil::CreateAacAdts(pFileSource->GetAudioParam().GetObjectType(), pFileSource->GetAudioParam().GetSampleRate(), pFileSource->GetAudioParam().GetChannel(), it->GetLength(), pAdts);
                    fwrite(pAdts, 1, MkAacAdtsLen, fpAudio);
                }
                fwrite(it->GetBuffer(), 1, it->GetLength(), fpAudio);
            }
        } else {
            MkListBuffer::const_iterator it = EsPacket.BufferList.GetBufferList().begin();
            for (; it != EsPacket.BufferList.GetBufferList().end(); it++) {
                fwrite(&NaluStartCode, 1, 4, fpVideo);
                fwrite(it->GetBuffer(), 1, it->GetLength(), fpVideo);
            }
        }
        return NoneError;
    });
}

void FileSourcePsDemuxerAndMuxer(const MkString& PsFile, const MkString& OutFile)
{
    FILE *fpPs = fopen(PsFile.c_str(), "rb");
    FILE *fpOut = fopen(OutFile.c_str(), "wb");
    CMkPsFileSource*  pFileSource = new CMkPsFileSource(fpPs, g_pTimer);
    pFileSource->StartMediaSource([](CMkMediaSource* pMediaSource, Uint32 ErrorCode) {
        return NoneError;
    }, [fpOut, fpPs, pFileSource](const MkEsPacket& EsPacket, const CMkVideoParam& VideoParam, const CMkAudioParam& AudioParam) {
        //audio
        if (EsPacket.BufferList.Empty()) {
            g_pTimer->LoopBreak();
            fclose(fpOut);
            fclose(fpPs);
            pFileSource->StopMediaSource();
            return NoneError;
        }
        CMkBufferList BufferList;
        Uint32 nUsed = 0;
        Uint8 pBuf[Len2K] = { 0 };
        CMkPsMuxer::PacketEsPacket(pFileSource->GetVideoParam(), pFileSource->GetAudioParam(), EsPacket, pBuf, Len2K, nUsed, BufferList);
        MkListBuffer::const_iterator it = BufferList.GetBufferList().begin();
        for (; it != BufferList.GetBufferList().end(); it++) {
            fwrite(it->GetBuffer(), 1, it->GetLength(), fpOut);
        }
        return NoneError;
    });
}

void PsDemuxerAndMuxer(const MkString& PsFile, const MkString& OutFile)
{

}

int main(int argc, char** argv)
{
    ParseH264();
    //MkString PsFile = "C:/Workspace/media/YBWM.ps";
    //MkString VideoFile = PsFile + ".video.dat";
    //MkString AudioFile = PsFile + ".audio.dat";
    //MkString OutFile = PsFile + ".out.dat";
    //CMkTimer Timer;
    //g_pTimer = &Timer;
    //PsDemuxer(PsFile, AudioFile, VideoFile);
    ////FileSourcePsDemuxerAndMuxer(PsFile, OutFile);
    //Timer.Dispatch();
    return 1;
}



